#pragma once

#include "application/pathfinding/multi_agent_solver.h"
#include "application/pathfinding/pathfinding_graph.h"
#include "kernel/interfaces/ILogger.h"
#include <QObject>
#include <QFuture>
#include <QFutureWatcher>
#include <QMutex>
#include <QSet>
#include <QString>
#include <QVector>
#include <atomic>
#include <memory>
#include <optional>
#include <vector>
#include <QHash>

#include "infrastructure/tasking/cancellation_token.h"

namespace application {
namespace dispatcher {

/**
 * @brief 并发多组合MAPF求解器
 * @details 同时尝试多种AGV组合进行路径规划，返回第一个成功的结果
 *
 * 核心思想：
 * - 生成多个候选组合（全集、N-1子集等）
 * - 并发执行MAPF求解
 * - 第一个成功的解立即返回，取消其他求解
 * - 提高规划成功率，降低平均延迟
 */
class ConcurrentCombinationSolver : public QObject {
    Q_OBJECT

public:
    /**
     * @brief 求解候选组合
     */
    struct SolveCandidate {
        std::vector<pathfinding::AgentRequest> requests;  // 该组合包含的请求
        int priority{0};                                   // 优先级（数字越小越重要）
        QSet<int> includedAgvs;                           // 包含的AGV编号
        QSet<int> excludedAgvs;                           // 排除的AGV编号
        QHash<int, QString> waitingAgvOriginalGoals;      // 等待车原始目标 (AGV编号 -> 真正想去的目标)

        SolveCandidate() = default;
    };

    /**
     * @brief 求解结果
     */
    struct SolveResult {
        bool success{false};                               // 是否成功
        std::vector<pathfinding::AgentPlan> plans;        // 规划结果
        QSet<int> solvedAgvs;                             // 成功规划的AGV
        QSet<int> failedAgvs;                             // 未规划的AGV
        int candidateIndex{-1};                           // 使用的候选索引
        double solveTime{0.0};                            // 求解耗时（秒）
        QString errorMessage;                             // 错误信息
        QHash<int, QString> waitingAgvOriginalGoals;      // 等待车原始目标 (AGV编号 -> 真正想去的目标)
    };

    explicit ConcurrentCombinationSolver(QObject* parent = nullptr);
    ~ConcurrentCombinationSolver() override;

    /**
     * @brief 并发求解多个组合，返回第一个成功的结果
     * @param candidates 候选组合列表
     * @param graph 路径规划图
     * @param logger 日志记录器
     * @param timeout 单个候选的超时时间（秒）
     * @return 求解结果
     */
    SolveResult solveWithFallback(
        const std::vector<SolveCandidate>& candidates,
        PathfindingGraphPtr graph,
        std::shared_ptr<kernel::ILogger> logger,
        double timeout = 1.5
    );

    /**
     * @brief 生成候选组合（全集 + N-1子集）
     * @param requests 所有请求
     * @param maxCandidates 最多生成的候选数量（0表示无限制）
     * @return 候选组合列表
     */
    static std::vector<SolveCandidate> generateCandidates(
        const std::vector<pathfinding::AgentRequest>& requests,
        int maxCandidates = 6
    );

private:
    // 内部辅助：按 goal 分组，返回 goal -> requests
    static QHash<QString, std::vector<pathfinding::AgentRequest>> groupByGoal(
        const std::vector<pathfinding::AgentRequest>& requests);
    // 选择单目标组 winner（当前简单按 agvNumber 最小），并生成等待集合（start==goal）
    static std::pair<pathfinding::AgentRequest, std::vector<pathfinding::AgentRequest>> pickWinnerAndWaiters(
        const std::vector<pathfinding::AgentRequest>& group);
    // 计算组合“粗评分”（可扩展：优先级/距离/能耗/风险）
    static int scoreCombo(const SolveCandidate& combo);

    /**
     * @brief 后台线程执行的求解任务
     */
    struct SolveTask {
        SolveCandidate candidate;
        PathfindingGraphPtr graph;
        std::shared_ptr<kernel::ILogger> logger;
        double timeout{0.0};
        double suboptimality{1.5};
        int candidateIndex;
        std::shared_ptr<std::atomic<bool>> cancelFlag;  // 取消标志
        base::tasking::CancellationTokenPtr cancellationToken;
    };

    /**
     * @brief 执行单个候选的求解（在线程池中执行）
     */
    static SolveResult executeSolveTask(const SolveTask& task);

    // 同步控制
    QMutex m_resultMutex;                              // 保护结果访问
    std::atomic<bool> m_solutionFound{false};          // 是否已找到解
    std::optional<SolveResult> m_bestResult;           // 最佳结果
};

} // namespace dispatcher
} // namespace application
